package com.luo.backend.service;

import com.luo.backend.dto.SendCodeResponse;
import com.luo.backend.entity.EmailVerificationCode;
import com.luo.backend.repository.EmailVerificationCodeRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Optional;
import java.util.Random;

/**
 * 邮箱验证码服务
 */
@Service
public class EmailVerificationService {
    
    private static final Logger logger = LoggerFactory.getLogger(EmailVerificationService.class);
    
    // 验证码有效期（分钟）
    private static final int CODE_EXPIRY_MINUTES = 5;
    
    // 发送间隔（分钟）
    private static final int SEND_INTERVAL_MINUTES = 5;
    
    @Autowired
    private EmailVerificationCodeRepository verificationCodeRepository;
    
    @Autowired
    private EmailService emailService;
    
    /**
     * 发送验证码
     */
    @Transactional
    public SendCodeResponse sendVerificationCode(String email, String type, HttpServletRequest request) {
        // 1. 检查频率限制
        if (hasRecentCode(email, type)) {
            throw new RuntimeException("该邮箱5分钟内已发送验证码，请稍后再试");
        }
        
        // 2. 生成6位随机验证码
        String code = generateSixDigitCode();
        
        // 3. 获取客户端IP
        String ipAddress = getClientIp(request);
        
        // 4. 计算过期时间
        LocalDateTime expiresAt = LocalDateTime.now().plusMinutes(CODE_EXPIRY_MINUTES);
        
        // 5. 保存到数据库
        EmailVerificationCode verificationCode = new EmailVerificationCode(
            email, code, type, expiresAt, ipAddress
        );
        verificationCodeRepository.save(verificationCode);
        
        // 6. 发送邮件
        try {
            emailService.sendVerificationCode(email, code, type);
            logger.info("验证码发送成功 - 邮箱: {}, 类型: {}, 过期时间: {}", email, type, expiresAt);
        } catch (Exception e) {
            logger.error("验证码邮件发送失败 - 邮箱: {}, 错误: {}", email, e.getMessage());
            throw new RuntimeException("验证码发送失败，请稍后重试");
        }
        
        // 7. 返回响应
        return new SendCodeResponse(email, expiresAt);
    }
    
    /**
     * 验证验证码
     */
    public boolean verifyCode(String email, String code, String type) {
        Optional<EmailVerificationCode> verificationCodeOpt = 
            verificationCodeRepository.findByEmailAndCodeAndType(email, code, type);
        
        if (!verificationCodeOpt.isPresent()) {
            logger.warn("验证码不存在 - 邮箱: {}, 验证码: {}, 类型: {}", email, code, type);
            return false;
        }
        
        EmailVerificationCode verificationCode = verificationCodeOpt.get();
        
        // 检查是否过期
        if (verificationCode.isExpired()) {
            logger.warn("验证码已过期 - 邮箱: {}, 过期时间: {}", email, verificationCode.getExpiresAt());
            return false;
        }
        
        // 检查是否已使用
        if (verificationCode.isUsed()) {
            logger.warn("验证码已使用 - 邮箱: {}, 使用时间: {}", email, verificationCode.getUsedAt());
            return false;
        }
        
        logger.info("验证码验证成功 - 邮箱: {}, 类型: {}", email, type);
        return true;
    }
    
    /**
     * 查找有效的验证码
     */
    public EmailVerificationCode findValidCode(String email, String code, String type) {
        Optional<EmailVerificationCode> verificationCodeOpt = 
            verificationCodeRepository.findByEmailAndCodeAndType(email, code, type);
        
        if (!verificationCodeOpt.isPresent()) {
            return null;
        }
        
        EmailVerificationCode verificationCode = verificationCodeOpt.get();
        
        if (!verificationCode.isValid()) {
            return null;
        }
        
        return verificationCode;
    }
    
    /**
     * 标记验证码为已使用
     */
    @Transactional
    public void markAsUsed(EmailVerificationCode verificationCode) {
        verificationCode.setUsedAt(LocalDateTime.now());
        verificationCodeRepository.save(verificationCode);
        logger.info("验证码已标记为已使用 - ID: {}, 邮箱: {}", 
            verificationCode.getId(), verificationCode.getEmail());
    }
    
    /**
     * 检查是否在规定时间内已发送过验证码（频率限制）
     */
    public boolean hasRecentCode(String email, String type) {
        LocalDateTime cutoffTime = LocalDateTime.now().minusMinutes(SEND_INTERVAL_MINUTES);
        long count = verificationCodeRepository.countByEmailAndTypeAndCreatedAtAfter(
            email, type, cutoffTime
        );
        return count > 0;
    }
    
    /**
     * 生成6位随机数字验证码
     */
    private String generateSixDigitCode() {
        Random random = new Random();
        int code = random.nextInt(900000) + 100000; // 100000 - 999999
        return String.valueOf(code);
    }
    
    /**
     * 获取客户端IP地址
     */
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        // 如果有多个IP，取第一个
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0].trim();
        }
        return ip;
    }
    
    /**
     * 清理过期验证码（定时任务调用）
     */
    @Transactional
    public void cleanExpiredCodes() {
        LocalDateTime cutoffTime = LocalDateTime.now().minusHours(24);
        verificationCodeRepository.deleteByCreatedAtBefore(cutoffTime);
        logger.info("已清理24小时前的验证码数据");
    }
}



